
#include "main.h"


#define gpio_CH1_TX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH1_TX_PORT		GPIOA
#define gpio_CH1_TX_PIN			GPIO_Pin_9
#define gpio_CH1_TX_AFTYPE		eAFCLK_APB2
#define gpio_CH1_TX_AFCLK		RCC_APB2Periph_USART1
#define gpio_CH1_TX_AFPINSRC	GPIO_PinSource9
#define gpio_CH1_TX_AF			GPIO_AF_USART1
#define gpio_CH1_RX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH1_RX_PORT		GPIOA
#define gpio_CH1_RX_PIN			GPIO_Pin_10
#define gpio_CH1_RX_AFTYPE		eAFCLK_APB2
#define gpio_CH1_RX_AFCLK		RCC_APB2Periph_USART1
#define gpio_CH1_RX_AFPINSRC	GPIO_PinSource10
#define gpio_CH1_RX_AF			GPIO_AF_USART1
#define uart_CH1_PORT			USART1
#define uart_CH1_IRQ			USART1_IRQn

#if		defined(BSP_DEVICE_TOUCH)

#define gpio_CH2_TX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH2_TX_PORT		GPIOA
#define gpio_CH2_TX_PIN			GPIO_Pin_2
#define gpio_CH2_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH2_TX_AFCLK		RCC_APB1Periph_USART2
#define gpio_CH2_TX_AFPINSRC	GPIO_PinSource2
#define gpio_CH2_TX_AF			GPIO_AF_USART2
#define gpio_CH2_RX_CLK			RCC_AHB1Periph_GPIOA
#define gpio_CH2_RX_PORT		GPIOA
#define gpio_CH2_RX_PIN			GPIO_Pin_3
#define gpio_CH2_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH2_RX_AFCLK		RCC_APB1Periph_USART2
#define gpio_CH2_RX_AFPINSRC	GPIO_PinSource3
#define gpio_CH2_RX_AF			GPIO_AF_USART2
#define uart_CH2_PORT			USART2
#define uart_CH2_IRQ			USART2_IRQn

#define gpio_CH3_TX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_TX_PORT		GPIOB
#define gpio_CH3_TX_PIN			GPIO_Pin_10
#define gpio_CH3_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_TX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH3_TX_AF			GPIO_AF_USART3
#define gpio_CH3_RX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_RX_PORT		GPIOB
#define gpio_CH3_RX_PIN			GPIO_Pin_11
#define gpio_CH3_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_RX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH3_RX_AF			GPIO_AF_USART3
#define uart_CH3_PORT			USART3
#define uart_CH3_IRQ			USART3_IRQn

#if	(CAMERA_MAX_NUM > 2)
#define gpio_CH4_TX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH4_TX_PORT		GPIOC
#define gpio_CH4_TX_PIN			GPIO_Pin_10
#define gpio_CH4_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH4_TX_AFCLK		RCC_APB1Periph_UART4
#define gpio_CH4_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH4_TX_AF			GPIO_AF_UART4
#define gpio_CH4_RX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH4_RX_PORT		GPIOC
#define gpio_CH4_RX_PIN			GPIO_Pin_11
#define gpio_CH4_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH4_RX_AFCLK		RCC_APB1Periph_UART4
#define gpio_CH4_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH4_RX_AF			GPIO_AF_UART4
#define uart_CH4_PORT			UART4
#define uart_CH4_IRQ			UART4_IRQn

#define gpio_CH5_TX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH5_TX_PORT		GPIOC
#define gpio_CH5_TX_PIN			GPIO_Pin_12
#define gpio_CH5_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH5_TX_AFCLK		RCC_APB1Periph_UART5
#define gpio_CH5_TX_AFPINSRC	GPIO_PinSource12
#define gpio_CH5_TX_AF			GPIO_AF_UART5
#define gpio_CH5_RX_CLK			RCC_AHB1Periph_GPIOD
#define gpio_CH5_RX_PORT		GPIOD
#define gpio_CH5_RX_PIN			GPIO_Pin_2
#define gpio_CH5_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH5_RX_AFCLK		RCC_APB1Periph_UART5
#define gpio_CH5_RX_AFPINSRC	GPIO_PinSource2
#define gpio_CH5_RX_AF			GPIO_AF_UART5
#define uart_CH5_PORT			UART5
#define uart_CH5_IRQ			UART5_IRQn
#endif	//CAMERA_MAX_NUM

#elif	defined(BSP_DEVICE_CAMERA)

#define gpio_CH3_TX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_TX_PORT		GPIOB
#define gpio_CH3_TX_PIN			GPIO_Pin_10
#define gpio_CH3_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_TX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH3_TX_AF			GPIO_AF_USART3
#define gpio_CH3_RX_CLK			RCC_AHB1Periph_GPIOB
#define gpio_CH3_RX_PORT		GPIOB
#define gpio_CH3_RX_PIN			GPIO_Pin_11
#define gpio_CH3_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH3_RX_AFCLK		RCC_APB1Periph_USART3
#define gpio_CH3_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH3_RX_AF			GPIO_AF_USART3
#define uart_CH3_PORT			USART3
#define uart_CH3_IRQ			USART3_IRQn

#define gpio_CH4_TX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH4_TX_PORT		GPIOC
#define gpio_CH4_TX_PIN			GPIO_Pin_10
#define gpio_CH4_TX_AFTYPE		eAFCLK_APB1
#define gpio_CH4_TX_AFCLK		RCC_APB1Periph_UART4
#define gpio_CH4_TX_AFPINSRC	GPIO_PinSource10
#define gpio_CH4_TX_AF			GPIO_AF_UART4
#define gpio_CH4_RX_CLK			RCC_AHB1Periph_GPIOC
#define gpio_CH4_RX_PORT		GPIOC
#define gpio_CH4_RX_PIN			GPIO_Pin_11
#define gpio_CH4_RX_AFTYPE		eAFCLK_APB1
#define gpio_CH4_RX_AFCLK		RCC_APB1Periph_UART4
#define gpio_CH4_RX_AFPINSRC	GPIO_PinSource11
#define gpio_CH4_RX_AF			GPIO_AF_UART4
#define uart_CH4_PORT			UART4
#define uart_CH4_IRQ			UART4_IRQn

#endif	//BSP_DEVICE_xxx

#define	rx_BUF_MAXLEN			4096


static struct
{
	USART_TypeDef*	Port;

	u8	TxBuf[rx_BUF_MAXLEN];
	u32	TxHead;
	u32	TxTail;

	u8	RxBuf[rx_BUF_MAXLEN];
	u32	RxHead;
	u32	RxTail;

	u8	PktBuf[UART_PKT_MAX_LEN];
	u32	PktCnt;
	u32	PktLen;

} _Uarts[eUART_MAX] = {
#if		defined(BSP_DEVICE_TOUCH)

	{uart_CH2_PORT,},
	{uart_CH3_PORT,},
#if	(CAMERA_MAX_NUM > 2)
	{uart_CH4_PORT,},
	{uart_CH5_PORT,},
#endif

#elif	defined(BSP_DEVICE_CAMERA)

	{uart_CH3_PORT,},
	{uart_CH4_PORT,},

#endif	//BSP_DEVICE_xxx
};

#if		defined(BSP_DEVICE_TOUCH)
static struct
{
	u32		LastTickCount;
	u32		PingTickCount[CAMERA_MAX_NUM];
} _UartsPing = {
	0,
};
#endif	//BSP_DEVICE_TOUCH



void Uart_Init(void)
{
	GPIO_INIT gis[] =
	{
		{gpio_CH1_TX_CLK, {gpio_CH1_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH1_TX_PORT,
			gpio_CH1_TX_AFTYPE, gpio_CH1_TX_AFCLK, gpio_CH1_TX_AFPINSRC, gpio_CH1_TX_AF},
		{gpio_CH1_RX_CLK, {gpio_CH1_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH1_RX_PORT,
			gpio_CH1_RX_AFTYPE, gpio_CH1_RX_AFCLK, gpio_CH1_RX_AFPINSRC, gpio_CH1_RX_AF},

#if		defined(BSP_DEVICE_TOUCH)

		{gpio_CH2_TX_CLK, {gpio_CH2_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH2_TX_PORT,
			gpio_CH2_TX_AFTYPE, gpio_CH2_TX_AFCLK, gpio_CH2_TX_AFPINSRC, gpio_CH2_TX_AF},
		{gpio_CH2_RX_CLK, {gpio_CH2_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH2_RX_PORT,
			gpio_CH2_RX_AFTYPE, gpio_CH2_RX_AFCLK, gpio_CH2_RX_AFPINSRC, gpio_CH2_RX_AF},
		{gpio_CH3_TX_CLK, {gpio_CH3_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_TX_PORT,
			gpio_CH3_TX_AFTYPE, gpio_CH3_TX_AFCLK, gpio_CH3_TX_AFPINSRC, gpio_CH3_TX_AF},
		{gpio_CH3_RX_CLK, {gpio_CH3_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_RX_PORT,
			gpio_CH3_RX_AFTYPE, gpio_CH3_RX_AFCLK, gpio_CH3_RX_AFPINSRC, gpio_CH3_RX_AF},
#if	(CAMERA_MAX_NUM > 2)
		{gpio_CH4_TX_CLK, {gpio_CH4_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH4_TX_PORT,
			gpio_CH4_TX_AFTYPE, gpio_CH4_TX_AFCLK, gpio_CH4_TX_AFPINSRC, gpio_CH4_TX_AF},
		{gpio_CH4_RX_CLK, {gpio_CH4_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH4_RX_PORT,
			gpio_CH4_RX_AFTYPE, gpio_CH4_RX_AFCLK, gpio_CH4_RX_AFPINSRC, gpio_CH4_RX_AF},
		{gpio_CH5_TX_CLK, {gpio_CH5_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH5_TX_PORT,
			gpio_CH5_TX_AFTYPE, gpio_CH5_TX_AFCLK, gpio_CH5_TX_AFPINSRC, gpio_CH5_TX_AF},
		{gpio_CH5_RX_CLK, {gpio_CH5_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH5_RX_PORT,
			gpio_CH5_RX_AFTYPE, gpio_CH5_RX_AFCLK, gpio_CH5_RX_AFPINSRC, gpio_CH5_RX_AF},
#endif	//CAMERA_MAX_NUM

#elif	defined(BSP_DEVICE_CAMERA)

		{gpio_CH3_TX_CLK, {gpio_CH3_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_TX_PORT,
			gpio_CH3_TX_AFTYPE, gpio_CH3_TX_AFCLK, gpio_CH3_TX_AFPINSRC, gpio_CH3_TX_AF},
		{gpio_CH3_RX_CLK, {gpio_CH3_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH3_RX_PORT,
			gpio_CH3_RX_AFTYPE, gpio_CH3_RX_AFCLK, gpio_CH3_RX_AFPINSRC, gpio_CH3_RX_AF},
		{gpio_CH4_TX_CLK, {gpio_CH4_TX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH4_TX_PORT,
			gpio_CH4_TX_AFTYPE, gpio_CH4_TX_AFCLK, gpio_CH4_TX_AFPINSRC, gpio_CH4_TX_AF},
		{gpio_CH4_RX_CLK, {gpio_CH4_RX_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_CH4_RX_PORT,
			gpio_CH4_RX_AFTYPE, gpio_CH4_RX_AFCLK, gpio_CH4_RX_AFPINSRC, gpio_CH4_RX_AF},

#endif	//BSP_DEVICE_xxx
	};

	UART_INIT uis[] =
	{	/* 115200, 256000, 1875000, 3750000 */
		#define _BAUDRATE	1875000

		{uart_CH1_PORT,
			{   115200, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH1_IRQ, 0, 1, ENABLE}},

#if		defined(BSP_DEVICE_TOUCH)

		{uart_CH2_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH2_IRQ, 0, 0, ENABLE}},
		{uart_CH3_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH3_IRQ, 0, 0, ENABLE}},
#if	(CAMERA_MAX_NUM > 2)
		{uart_CH4_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH4_IRQ, 0, 0, ENABLE}},
		{uart_CH5_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH5_IRQ, 0, 0, ENABLE}},
#endif	//CAMERA_MAX_NUM

#elif	defined(BSP_DEVICE_CAMERA)

		{uart_CH3_PORT,
			{_BAUDRATE, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH3_IRQ, 0, 0, ENABLE}},
		{uart_CH4_PORT,
			{   115200, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_Rx | USART_Mode_Tx), USART_HardwareFlowControl_None},
			{uart_CH4_IRQ, 0, 1, ENABLE}},

#endif	//BSP_DEVICE_xxx
	};

	Util_GpioInit(gis, _countof(gis));
	Util_UartInit(uis, _countof(uis));
}

int fputc(int ch, FILE *f)
{
	/*USART_SendData(uart_CH1_PORT, ch);
	while (USART_GetFlagStatus(uart_CH1_PORT, USART_FLAG_TXE) == RESET);*/
	uart_CH1_PORT->DR = (ch & (u16)0x01FF);
	while (0 == (uart_CH1_PORT->SR & USART_FLAG_TXE));

#if	defined(BSP_DEVICE_CAMERA)
	_Uarts[eUART_EXTRA].TxBuf[_Uarts[eUART_EXTRA].TxHead++] = ch;
	if (rx_BUF_MAXLEN <= _Uarts[eUART_EXTRA].TxHead) {
		_Uarts[eUART_EXTRA].TxHead = 0;
	}
	USART_ITConfig(_Uarts[eUART_EXTRA].Port, USART_IT_TXE, ENABLE);
#endif

	return ch;
}
void USART1_IRQHandler(void)
{
	/*if (SET == USART_GetITStatus(uart_CH1_PORT, USART_IT_RXNE)) {
		u8 rx = (u8)(uart_CH1_PORT->DR & 0xFF);
		fputc(rx, (FILE *)1);
	}
	if (SET == USART_GetITStatus(uart_CH1_PORT, USART_IT_TXE)) {
	}*/
}

static __INLINE void irqProcs(u8 uart)
{
	if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_IT_RXNE)) {
		u8 rxData = _Uarts[uart].Port->DR;

		_Uarts[uart].RxBuf[_Uarts[uart].RxHead++] = rxData;
		if (rx_BUF_MAXLEN == _Uarts[uart].RxHead)
			_Uarts[uart].RxHead = 0;
	} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_IT_TXE)) {
		u32 uHead = _Uarts[uart].TxHead;

		if (_Uarts[uart].TxTail == uHead) {
			USART_ITConfig(_Uarts[uart].Port, USART_IT_TXE, DISABLE);
		} else {
			_Uarts[uart].Port->DR = _Uarts[uart].TxBuf[_Uarts[uart].TxTail++];
			if (rx_BUF_MAXLEN == _Uarts[uart].TxTail)
				_Uarts[uart].TxTail = 0;
		}
	} else {
/*
#define USART_FLAG_CTS                       ((uint16_t)0x0200)
#define USART_FLAG_LBD                       ((uint16_t)0x0100)
	#define USART_FLAG_TXE                       ((uint16_t)0x0080)
#define USART_FLAG_TC                        ((uint16_t)0x0040)
	#define USART_FLAG_RXNE                      ((uint16_t)0x0020)
#define USART_FLAG_IDLE                      ((uint16_t)0x0010)
#define USART_FLAG_ORE                       ((uint16_t)0x0008)
#define USART_FLAG_NE                        ((uint16_t)0x0004)
#define USART_FLAG_FE                        ((uint16_t)0x0002)
#define USART_FLAG_PE                        ((uint16_t)0x0001)
*/
		if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_CTS)) {
			printf("%d-CTS\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_LBD)) {
			printf("%d-LBD\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_TC)) {
			printf("%d-TC\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_IDLE)) {
			printf("%d-IDLE\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_ORE)) {
			printf("%d-ORE\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_NE)) {
			printf("%d-NE\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_FE)) {
			printf("%d-FE\r\n", uart);
		} else if (SET == USART_GetITStatus(_Uarts[uart].Port, USART_FLAG_PE)) {
			printf("%d-PE\r\n", uart);
		}
	}
}

#if		defined(BSP_DEVICE_TOUCH)

void USART2_IRQHandler(void)
{
	irqProcs(eUART_CAM1);
}
void USART3_IRQHandler(void)
{
	irqProcs(eUART_CAM2);
}
#if	(CAMERA_MAX_NUM > 2)
void UART4_IRQHandler(void)
{
	irqProcs(eUART_CAM3);
}
void UART5_IRQHandler(void)
{
	irqProcs(eUART_CAM4);
}
#endif	//CAMERA_MAX_NUM

#elif	defined(BSP_DEVICE_CAMERA)

void USART3_IRQHandler(void)
{
	irqProcs(eUART_TOUCH);
}
void UART4_IRQHandler(void)
{
	irqProcs(eUART_EXTRA);
}

#endif	//BSP_DEVICE_xxx


static void uartPkt_Parsing(u8 uart, u16 wPktLen, u8 *pPktData);


void Uart_PktProc(void)
{
	for (u32 uart=0; uart<eUART_MAX; uart++) {
		u32 wHead = _Uarts[uart].RxHead;
		if (_Uarts[uart].RxTail == wHead) {
			continue;
		}

		u32 wCount = (((wHead + rx_BUF_MAXLEN) - _Uarts[uart].RxTail) % rx_BUF_MAXLEN);
		for (u32 i=0; i<wCount; i++) {
			_Uarts[uart].PktBuf[_Uarts[uart].PktCnt++] = _Uarts[uart].RxBuf[_Uarts[uart].RxTail++];
			if (rx_BUF_MAXLEN == _Uarts[uart].RxTail)
				_Uarts[uart].RxTail = 0;

			if (UART_PKT_POS_SOH1 == _Uarts[uart].PktCnt) {
				_Uarts[uart].PktLen = 0;
				if (UART_PKT_SOHS[UART_PKT_POS_SOH0] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH0]) {
					_Uarts[uart].PktCnt = 0;
				}
			} else if (UART_PKT_POS_SOH2 == _Uarts[uart].PktCnt) {
				if (UART_PKT_SOHS[UART_PKT_POS_SOH1] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH1]) {
					_Uarts[uart].PktCnt = 0;
				}
			} else if (UART_PKT_POS_SOH3 == _Uarts[uart].PktCnt) {
				if (UART_PKT_SOHS[UART_PKT_POS_SOH2] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH2]) {
					_Uarts[uart].PktCnt = 0;
				}
			} else if (UART_PKT_POS_CMD == _Uarts[uart].PktCnt) {
				if (UART_PKT_SOHS[UART_PKT_POS_SOH3] != _Uarts[uart].PktBuf[UART_PKT_POS_SOH3]) {
					_Uarts[uart].PktCnt = 0;
				}
			} else if (UART_PKT_POS_DATA == _Uarts[uart].PktCnt) {
				u32 wDataLen = MAKEWORD(_Uarts[uart].PktBuf[UART_PKT_POS_DLEN0], _Uarts[uart].PktBuf[UART_PKT_POS_DLEN1]);
				_Uarts[uart].PktLen = wDataLen + UART_PKT_HEAD_LEN;
			}

			if (_Uarts[uart].PktCnt && (_Uarts[uart].PktLen == _Uarts[uart].PktCnt)) {
				uartPkt_Parsing(uart, _Uarts[uart].PktLen, _Uarts[uart].PktBuf);
				_Uarts[uart].PktCnt = 0;
			}
		}
	}

#if		defined(BSP_DEVICE_TOUCH)
	if (0 == (g_vu32SysTickCount % 3000)) {	// 3, 6, 9, ...
		if (_UartsPing.LastTickCount != g_vu32SysTickCount) {
			_UartsPing.LastTickCount = g_vu32SysTickCount;

			for (u32 i=0; i<CAMERA_MAX_NUM; i++) {
				if (_UartsPing.PingTickCount[i] < g_vu32SysTickCount) {
					if (g_TCD.bBeepAlert) {
						printf("EVT_CAMERA_PING : ERROR TIMEOUT %d\r\n", i);
						g_u32BuzzerDelay = g_vu32SysTickCount + (100 * 10);	// *[10msec]
						Led_Set(eLED_BUZZER, 1);
					}
					break;
				}
			}
		}
	}
#endif	//BSP_DEVICE_TOUCH
}

void Uart_PktCmd(u8 uart, u8 cmd, u8 dev, u16 len, u8 *data)
{
	u32 i, nLen, nLenTmp;
	u8 head[UART_PKT_HEAD_LEN];

	memcpy(head, UART_PKT_SOHS, 4);
	head[UART_PKT_POS_CMD]   = cmd;
	head[UART_PKT_POS_DEV]   = dev;
	head[UART_PKT_POS_DLEN0] = LOBYTE(len);
	head[UART_PKT_POS_DLEN1] = HIBYTE(len);

	nLen = _Uarts[uart].TxHead + UART_PKT_HEAD_LEN;
	if (rx_BUF_MAXLEN > nLen) {
		for (i=0; i<UART_PKT_HEAD_LEN; i++) {
			_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = head[i];
		}
	} else {
		nLenTmp = rx_BUF_MAXLEN - _Uarts[uart].TxHead;
		for (i=0; i<nLenTmp; i++) {
			_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = head[i];
		}
		_Uarts[uart].TxHead = 0;
		nLenTmp += (nLen % rx_BUF_MAXLEN);
		for (; i<nLenTmp; i++) {
			_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = head[i];
		}
	}

	if (len) {
		nLen = _Uarts[uart].TxHead + len;
		if (rx_BUF_MAXLEN > nLen) {
			for (i=0; i<len; i++) {
				_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = data[i];
			}
		} else {
			nLenTmp = rx_BUF_MAXLEN - _Uarts[uart].TxHead;
			for (i=0; i<nLenTmp; i++) {
				_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = data[i];
			}
			_Uarts[uart].TxHead = 0;
			nLenTmp += (nLen % rx_BUF_MAXLEN);
			for (; i<nLenTmp; i++) {
				_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = data[i];
			}
		}
	}

	USART_ITConfig(_Uarts[uart].Port, USART_IT_TXE, ENABLE);
}

void Uart_PktRes(u8 uart, u8 req, u8 dev, u8 cmd, u16 len, u8 *data)
{
	u32 i, nLen, nLenTmp;
	u8 head[UART_PKT_HEAD_LEN];

	memcpy(head, UART_PKT_SOHS, 4);
	head[UART_PKT_POS_CMD]   = req;
	head[UART_PKT_POS_DEV]   = dev;
	head[UART_PKT_POS_DLEN0] = LOBYTE(len) + 1;
	head[UART_PKT_POS_DLEN1] = HIBYTE(len);

	nLen = _Uarts[uart].TxHead + UART_PKT_HEAD_LEN;
	if (rx_BUF_MAXLEN > nLen) {
		for (i=0; i<UART_PKT_HEAD_LEN; i++) {
			_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = head[i];
		}
	} else {
		nLenTmp = rx_BUF_MAXLEN - _Uarts[uart].TxHead;
		for (i=0; i<nLenTmp; i++) {
			_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = head[i];
		}
		_Uarts[uart].TxHead = 0;
		nLenTmp += (nLen % rx_BUF_MAXLEN);
		for (; i<nLenTmp; i++) {
			_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = head[i];
		}
	}

	_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = cmd;
	if (rx_BUF_MAXLEN == _Uarts[uart].TxHead)
		_Uarts[uart].TxHead = 0;

	if (len) {
		nLen = _Uarts[uart].TxHead + len;
		if (rx_BUF_MAXLEN > nLen) {
			for (i=0; i<len; i++) {
				_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = data[i];
			}
		} else {
			nLenTmp = rx_BUF_MAXLEN - _Uarts[uart].TxHead;
			for (i=0; i<nLenTmp; i++) {
				_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = data[i];
			}
			_Uarts[uart].TxHead = 0;
			nLenTmp += (nLen % rx_BUF_MAXLEN);
			for (; i<nLenTmp; i++) {
				_Uarts[uart].TxBuf[_Uarts[uart].TxHead++] = data[i];
			}
		}
	}

	USART_ITConfig(_Uarts[uart].Port, USART_IT_TXE, ENABLE);
}
void Uart_PktEvt(u8 uart, u8 evt, u8 dev, u16 len, u8 *data)
{
	Uart_PktCmd(uart, evt, dev, len, data);
}

static void uartPkt_Parsing(u8 uart, u16 wPktLen, u8 *pPktData)
{
	u8 cmd, *pdev, *pdata, err = ERR_SUCCESS;
	u16 dlen;

	cmd   =  pPktData[UART_PKT_POS_CMD];
	pdev  = &pPktData[UART_PKT_POS_DEV];
	dlen  =  MAKEWORD(pPktData[UART_PKT_POS_DLEN0], pPktData[UART_PKT_POS_DLEN1]);
	pdata = &pPktData[UART_PKT_POS_DATA];

#if		defined(BSP_DEVICE_TOUCH)
#if		defined(BSP_APP)
	{
		u32 idx = (*pdev - DEV_CAMERA1);
		if (CAMERA_MAX_NUM > idx) {
			Led_Toggle(eLED_PORT1 + idx);
			_UartsPing.PingTickCount[idx] = g_vu32SysTickCount + 5000;
		}
	}

	switch (cmd) {
	case EVT_CAMERA_INIT:
	case EVT_IMAGE_SIDEVIEW:
	case EVT_IMAGE_DETECTION:
	case EVT_RADIAN_DATA:
		break;
	case EVT_LINEEQ_DATA:
		Touch_AddData(*pdev, dlen, pdata);
		return;
	case EVT_CAMERA_PING:
		if (CAMERA_MAX_NUM > uart) {
			if ((DEV_CAMERA1 + uart) != *pdev) {
				printf("EVT_CAMERA_PING : ERROR DEV (%d != %d)\r\n", *pdev, (DEV_CAMERA1 + uart));
				if (g_TCD.bBeepAlert) {
					g_u32BuzzerDelay = g_vu32SysTickCount + (50 * 10);	// *[10msec]
					Led_Set(eLED_BUZZER, 1);
				}
			}
		}
		return;
	}

	Usb_PktCmdEvt(cmd, *pdev, dlen, pdata);
	(void)err;		// warning
#else
	(void)cmd;		// warning
	(void)*pdev;	// warning
	(void)*pdata;	// warning
	(void)err;		// warning
	(void)dlen;		// warning
#endif	//BSP_APP

#elif	defined(BSP_DEVICE_CAMERA)

	err = ERR_UNKNOWN_DEVICE;
	if (CMD_RESET == cmd) {
		err = Pkt_CmdProc(uart, cmd, *pdev, &dlen, pdata);
		// reset
	} else if (g_u8MyAddr == *pdev) {
		err = Pkt_CmdProc(uart, cmd, *pdev, &dlen, pdata);
	}

	if (ERR_SUCCESS == err) {
		Uart_PktRes(uart, CMD_RESULT_SUCCESS, *pdev, cmd, dlen, pdata);
	} else {
		#if	DBG_MSG_UART
		printf("err(%d) : cmd(%02X) dev(%d) dlen(%02X)\r\n", err, cmd, *pdev, dlen);
		#endif	//DBG_MSG_UART
		Uart_PktRes(uart, CMD_RESULT_ERROR, *pdev, cmd, 1, (u8 *)&err);
	}
#endif	//BSP_DEVICE_xxx
}

